import 'dart:convert';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';

class ApiInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // print("请求之前");
    // 在请求之前添加头部或认证信息
    // options.headers['Authorization'] = 'Bearer token';
    // options.headers['Content-Type'] = 'application/json';
    handler.next(options);
  }

  // 是否打印日志结果
  bool isPrintLogResult = false;

  // 过长的文本是否省略
  bool isEllipsis = false;

  // 如果是列表，则打印多少条数据，如果是null，则全部打印
  int? printListSize = null;

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    printHttpLog(response);
    handler.next(response);
  }

  ///
  void printHttpLog(Response response) {
    if (!isPrintLogResult) return;
    try {
      var map = jsonDecode(response.toString());
      printMap(map, 0, "", false);
    } catch (e) {
      debugPrint("response decode err $e");
    }
  }

  void printMap(Map map, int level, String k, isPrintComma) {
    debugPrint("${getT(level)}${getK(k)}{");
    var len = map.length;
    var index = 0;
    map.forEach((k, v) {
      bool b = index != len - 1;
      if (v is List) {
        printList(v, level + 1, k, b);
      } else if (v is Map) {
        printMap(v, level + 1, k, b);
      } else if (v is String) {
        if (isEllipsis && v.length > 5) {
          v = "${v.substring(0, 5)}***";
        }
        debugPrint("${getT(level + 1)}${getK(k)}\"$v\"${getComa(b)}");
      } else {
        debugPrint("${getT(level + 1)}${getK(k)}$v${getComa(b)}");
      }
      index++;
    });
    debugPrint("${getT(level)}}${getComa(isPrintComma)}");
  }

  void printList(List list, int level, String k, bool isPrintComma) {
    debugPrint("${getT(level)}${getK(k)}[");
    int index = 0;
    for (var value in list) {
      if (value is Map) {
        printMap(value, level + 1, "",
            index != (printListSize ?? 0) - 1 && index != list.length - 1);
      }
      if (printListSize == index + 1 || printListSize == 0) {
        break;
      }
      index++;
    }
    debugPrint("${getT(level)}]${getComa(isPrintComma)}");
  }

  String getT(int level) {
    String r = "";
    for (int i = 0; i < level; i++) {
      r += " ";
    }
    return r;
  }

  String getK(String k) {
    if (k.isEmpty) {
      return '';
    }
    return "\"$k\":";
  }

  String getComa(bool isPrint) {
    return isPrint ? ',' : '';
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    // 处理网络请求错误

    handler.next(err);
    // handler.next(err);
    SmartDialog.showToast(await dioError(err));
    super.onError(err, handler);
  }

  static Future dioError(DioException error) async {
    switch (error.type) {
      case DioExceptionType.badCertificate:
        return '证书有误！';
      case DioExceptionType.badResponse:
        return '服务器异常，请稍后重试！';
      case DioExceptionType.cancel:
        return "请求已被取消，请重新请求";
      case DioExceptionType.connectionError:
        return '连接错误，请检查网络设置';
      case DioExceptionType.connectionTimeout:
        return "网络连接超时，请检查网络设置";
      case DioExceptionType.receiveTimeout:
        return "响应超时，请稍后重试！";
      case DioExceptionType.sendTimeout:
        return "发送请求超时，请检查网络设置";
      case DioExceptionType.unknown:
        var res = await checkConnect();
        return res + " \n 网络异常，请稍后重试！";
      default:
        return "Dio异常";
    }
  }

  static Future<dynamic> checkConnect() async {
    final connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      return 'connected with mobile network';
    } else if (connectivityResult == ConnectivityResult.wifi) {
      return 'connected with wifi network';
    } else if (connectivityResult == ConnectivityResult.ethernet) {
      // I am connected to a ethernet network.
    } else if (connectivityResult == ConnectivityResult.vpn) {
      // I am connected to a vpn network.
      // Note for iOS and macOS:
      // There is no separate network interface type for [vpn].
      // It returns [other] on any device (also simulator)
    } else if (connectivityResult == ConnectivityResult.other) {
      // I am connected to a network which is not in the above mentioned networks.
    } else if (connectivityResult == ConnectivityResult.none) {
      return 'not connected to any network';
    }
  }
}
